﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using Citi.Helpers;
using EO.WebBrowser;
using EO.WebBrowser.WinForm;

namespace Citi.Inquiry.Extractor.Util
{
    public class InquiryExtract
    {
        WebView webBrowser;
        string TemplateReportName { get; set; }
        Form FormParent { get; set; }
        string PathToSave { get; set; }
        string LocalPathToSave { get; set; }
        string LogPath { get; set; }
        string Parameters { get; set; }
        DownloadItem DownloadItem { get; set; }

        public void StartExtraction(WebControl webControl, string templateReportName, string url, string userLogin, string pathToSave,
            string parameters, Form form = null)
        {
            try
            {
                if (webControl == null)
                {
                    webControl = new WebControl();
                    webControl.WebView = new WebView();
                }

                LogPath = string.Format(ConfigurationManager.AppSettings["LogPath"], FileHelper.MakeValidFileName(templateReportName));

                try
                {
                    if (File.Exists(LogPath)) File.Delete(LogPath);
                }
                catch { }

                TemplateReportName = templateReportName;

                webBrowser = webControl.WebView;
                webBrowser.BeforeDownload += webBrowser_BeforeDownload;
                webBrowser.DownloadCompleted += webBrowser_DownloadCompleted;
                webBrowser.DownloadUpdated += webBrowser_DownloadUpdated;

                FormParent = form;
                PathToSave = pathToSave;
                Parameters = parameters;
                LocalPathToSave = Path.Combine(@"C:\temp", string.Concat(Guid.NewGuid(), Path.GetExtension(pathToSave)));

                if (File.Exists(LocalPathToSave)) File.Delete(LocalPathToSave);

                Log(string.Format("Logging on Single Sign On as {0}", userLogin));
                webControl.LogSingleSignOn(userLogin, SecurityHelper.LoginType.Sso, url);
                Log("Logged");

                OpenTemplateRunScreen();

                while (DownloadItem == null)
                {
                    Application.DoEvents();
                    Thread.Sleep(100);
                }

                Log(string.Format("Saving file on '{0}'", pathToSave));
                File.Copy(LocalPathToSave, pathToSave, true);
                File.Delete(LocalPathToSave);
            }
            catch (Exception e)
            {
                Log(string.Format("#ERROR {0}. INNER EXCEPTION: {1}", e.Message, e.InnerException != null ? e.InnerException.Message : string.Empty));
            }
            finally
            {
                Log("Extractor will be closed");

                try
                {
#if !DEBUG
                    Environment.Exit(Environment.ExitCode);
#endif
                }
                catch { }
            }
        }

        int lastDownloadPercent = 0;

        void webBrowser_DownloadUpdated(object sender, DownloadEventArgs e)
        {
            if (lastDownloadPercent != 0 && lastDownloadPercent != e.Item.PercentageComplete && e.Item.PercentageComplete % 10 == 0)
                Log(string.Format("{0}% completed", e.Item.PercentageComplete));

            lastDownloadPercent = e.Item.PercentageComplete;

            UpdateFormTitle(string.Format("{0}% completed", e.Item.PercentageComplete));
        }

        void webBrowser_DownloadCompleted(object sender, DownloadEventArgs e)
        {
            Log("Download finished");
            UpdateFormTitle("Download finished");
            DownloadItem = e.Item;
        }

        void webBrowser_BeforeDownload(object sender, BeforeDownloadEventArgs e)
        {
            Log("Download has been started");
            UpdateFormTitle("Downloading");
            e.FilePath = LocalPathToSave;
            e.ShowDialog = false;
        }

        void UpdateFormTitle(string message)
        {
            if (FormParent == null) return;

            FormParent.Text = string.Format("{0} - {1}", webBrowser.Title, message);
        }

        private void OpenTemplateRunScreen()
        {
            var templateTable = "document.getElementsByClassName('x-tree-node-text')";
            webBrowser.WaitUntilExist(templateTable, 120000);

            Log(string.Format("Looking for template report '{0}'", TemplateReportName));

            var javascript = string.Format(JavascriptQuery.FindTemplateReport, templateTable, TemplateReportName);

            var found = (bool)webBrowser.EvaluateScript(javascript);

            if (found)
            {
                var buttonRun = "menuitem-1433-itemEl";
                ClickOnElement(buttonRun, null, null);
                Log("Template found");
                RunReport();
            }
            else
            {
                Log(string.Format("#Error No report was found named '{0}'", TemplateReportName));
                Environment.Exit(Environment.ExitCode);
            }
        }

        private string FillParameters()
        {
            Wait(8000);
            Log("Getting report parameters");
            var parameters = GetParametersDictionary();
            var reportName = string.Format("{0}-{1}", TemplateReportName, Guid.NewGuid().ToString().Substring(0, 10));
            parameters.Add("Report Title", reportName);

            foreach (var parameter in parameters)
            {
                Log(string.Format("Parameter '{0}'. Value: '{1}'", parameter.Key, parameter.Value));
                webBrowser.EvaluateScript(string.Format(JavascriptQuery.FillParameter, parameter.Key, parameter.Value));

                Wait(1000);
            }

            return reportName;
        }

        private Dictionary<string, string> GetParametersDictionary()
        {
            var dictionary = new Dictionary<string, string>();

            if (string.IsNullOrWhiteSpace(Parameters)) return dictionary;

            var parametersSplited = Parameters.Split(new[] { @"]}" }, 200, StringSplitOptions.RemoveEmptyEntries);

            foreach (var parameter in parametersSplited)
            {
                var parameterSplited = parameter.Substring(2).Split(new[] { "][" }, 2, StringSplitOptions.RemoveEmptyEntries);

                dictionary.Add(parameterSplited[0], parameterSplited[1]);
            }

            return dictionary;
        }

        private void RunReport()
        {
            var reportName = FillParameters();
            ClickRunReport();
            DownloadReport(reportName);
        }

        private void DownloadReport(string reportName)
        {
            var reportCompleted = CheckReportCompleted(reportName);

            while (!reportCompleted)
            {
                Wait(2000);
                reportCompleted = CheckReportCompleted(reportName);
            }

            ClickDownloadReport(reportName);
        }

        private void ClickDownloadReport(string reportName)
        {
            var javascript = string.Format(JavascriptQuery.CheckReportGenerated, reportName, JavascriptQuery.ClickOnDownloadMenu,
                       string.Empty, string.Empty);

            webBrowser.EvaluateScript(javascript);
        }

        private bool CheckReportCompleted(string reportName)
        {
            var javascript = string.Format(JavascriptQuery.CheckReportGenerated, reportName, JavascriptQuery.CheckReportCompleted,
                        "var completed = false;", "completed;");

            return (bool)webBrowser.EvaluateScript(javascript);
        }

        private void Wait(int miliseconds)
        {
            var sleepTime = 100;
            var i = 0;
            while (i < miliseconds / sleepTime)
            {
                i++;
                Application.DoEvents();
                Thread.Sleep(sleepTime);
            }
        }

        private void ClickRunReport()
        {
            Wait(3000);
            Log("Starting to Run Report");
            webBrowser.EvaluateScript(JavascriptQuery.ClickRunButtonReport);
            Wait(5000);
        }

        bool ClickOnElement(string elementToClickId, NavigationTaskEventHandler eventRemove, NavigationTaskEventHandler eventAdd)
        {
            var javascriptClick = string.Format("document.getElementById('{0}')", elementToClickId);

            if (!webBrowser.AllElementExist(javascriptClick)) return false;

            if (eventRemove != null)
                webBrowser.LoadComplete -= eventRemove;

            if (eventAdd != null)
                webBrowser.LoadComplete += eventAdd;

            webBrowser.EvaluateScript(string.Format("{0}.click();", javascriptClick));
            return true;
        }

        void Log(string message)
        {
            try
            {
                File.AppendAllLines(LogPath, new[] { message });
            }
            catch
            {

            }
        }
    }
}
